package cn.xyt.service;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import cn.tom.db.jdbc.simple.DBQuery;
import cn.tom.db.jdbc.simple.DBUtil;
import cn.tom.kit.IoBuffer;
import cn.tom.kit.cache.TimedCache;
import cn.tom.kit.io.FileUtil;
import cn.xyt.dto.Battery;
import cn.xyt.dto.Message;
import cn.xyt.dto.VoltInfo;
import cn.xyt.util.ByteUtil;
import cn.xyt.util.HttpUtil;
import cn.xyt.util.JPushUtil;
import cn.xyt.util.MapUtil;
import cn.xyt.util.MessageThreadPool;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class MessageService extends BaseService{
	
	void createReg(int id, byte[] reg){
		byte [] b = ByteUtil.intToByteArray(id);
		long sum = ByteUtil.SumCheck(b);
		for(int i=0; i<reg.length; i++){
			reg[i] =  (byte) ~(reg[i] ^ sum);  // 先异或^, 然后取反~
		}
	}
	
	void initRegInfo(int deviceid){
		ArrayList<String> sqls = new ArrayList<>();
		sqls.add("insert into gpsone(did) values("+deviceid+")");
		sqls.add("insert into deviceone(did) values("+deviceid+")");
		sqls.add("insert into voltone(did) values("+deviceid+")");
		sqls.add("insert into battery(did) values("+deviceid+")");
		sqls.add("insert into life(did) values("+deviceid+")");
		sqls.add("insert into milleages(did) values("+deviceid+")");
		DBUtil.batchUpdate(sqls);
	}
	
	
	public byte[] register(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int length = body.readByte();  //长度
		byte[] regmsg = new byte[length];
		body.readBytes(regmsg);
		int deviceid =  body.readInt();
		IoBuffer resBody = getLittleBuf();
		// 生成鉴权码流数据
		createReg(deviceid, regmsg);
		BigInteger bigInteger = new BigInteger(regmsg);
		//TODO 添加注册信息, 检查最大注册次数
		String sql = "INSERT INTO deviceauth(id,auth,authcnt) VALUES (?,?,1) ON CONFLICT (id) DO UPDATE SET auth=?, authcnt = deviceauth.authcnt+1";
		DBUtil.exec(sql,  deviceid, bigInteger.longValue(), bigInteger.longValue());
		Integer regcnt = DBUtil.getInt("select authcnt from deviceauth where id =?", deviceid);
		if(regcnt==1) initRegInfo(deviceid);
		
		resBody.writeByte(regcnt<Integer.MAX_VALUE?1:3);  // 1第一次注册, 2已注册, 3 非法
		resBody.writeByte(length);
		resBody.writeBytes(regmsg);
		resBody.writeInt(deviceid);
		return resBody.flip().readBytes(0, resBody.limit());
	}
	
	/**
	 * 鉴权登录
	 * @param body
	 * @return
	 */
	public byte[] login(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		short serial = body.readShort();
		int loginsize = body.readByte();
		byte [] loginid = new byte[loginsize];
		body.readBytes(loginid);
		int bsize =  body.readByte();
		byte [] blebyte = new byte [bsize];
		body.readBytes(blebyte);
		String _bleid = new String(blebyte ,Charset.forName("UTF-8")) ;
		int deviceid = msg.getHeader().getDeviceid();
		DBUtil.exec("update deviceauth set bleid=?,ctime=now() where id=? and bleid<>?", _bleid, deviceid,_bleid);
		DBUtil.exec("update life set bleid=? where did=? and bleid<>?", _bleid, deviceid,_bleid);
		IoBuffer resBody = getLittleBuf();
		int cnt = DBUtil.getInt("select count(*) from deviceauth where auth =? and id=?", new BigInteger(loginid).longValue(),deviceid);
		// 登录状态
		int loginState = cnt==1 ? 1:2;
		
		resBody.writeByte(loginState);
		IoBuffer date = getLittleBuf(6);
		Calendar c = Calendar.getInstance();
		date.writeByte(c.get(Calendar.YEAR)-2000);
		date.writeByte(c.get(Calendar.MONTH));
		date.writeByte(c.get(Calendar.DAY_OF_MONTH));
		date.writeByte(c.get(Calendar.HOUR_OF_DAY));
		date.writeByte(c.get(Calendar.MINUTE));
		date.writeByte(c.get(Calendar.SECOND));
		resBody.writeBytes(date.array());
		return resBody.flip().readBytes(0, resBody.limit());
		
	}
	
	
	/**
	 * 心跳
	 * @param body
	 * @return
	 */
	public byte[] heart(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int state = body.readByte();
		int deviceid = msg.getHeader().getDeviceid();
		if(state ==0){ // 0有效定位, 1无效定位
			int year = 2000 + body.readByte();
			int month = body.readByte();
			int day = body.readByte();
			int hour = body.readByte() + 8; //时间 +8
			int minute = body.readByte();
			int second = body.readByte();
			char ew = (char) body.readByte(); // ‘E’东经 ‘W’西经
			double lon = (double)body.readInt()/1000000;   
			char ns = (char) body.readByte(); // ‘N’北纬  ‘S’南纬
			double lat = (double)body.readInt()/1000000;   
			if(lon<72 || lat <17){
				return null;
			}
			double[] lat_lon = MapUtil.wgs2gcj(lat, lon); // 转高德地图
			
			int height = body.readShort();
			int speed = body.readShort();
			int orientation  = body.readShort(); //方位
			int mileage = body.readInt(); //里程
			
			Calendar c = Calendar.getInstance();
			c.set(year, month-1, day, hour, minute, second);
			
			DBUtil.exec("INSERT INTO gpslog (did, lat, lon, ew, ns, height, speed, orientation, mileage, ctime) " +
					"VALUES(?,?,?,?,?,?,?,?,?,?)", deviceid, lat_lon[0],lat_lon[1],ew,ns,height,speed,orientation,mileage,new Timestamp(c.getTimeInMillis()));
			DBUtil.exec("update gpsone set lat =?,lon=?,height=?,speed=?,orientation=?, mileage=?, ctime=? where did=?", 
					lat_lon[0],lat_lon[1],height,speed,orientation,mileage,new Timestamp(c.getTimeInMillis()), deviceid);
			
		}
		
		return null;
		
	}
	
	/**
	 * 设备基础信息上报
	 * @param body
	 * @return
	 */
	public byte[] diviceInfo(Message msg) {
		
		IoBuffer body = msg.getBodyBuf();
		String softVersion = new StringBuffer()
				.append((int)body.readByte()&0xff).append('.')
				.append((int)body.readByte()&0xff).append('.')
				.append((int)body.readByte()&0xff).append('.')
				.append(String.format("%03d", (int)body.readByte()&0xff)).toString();
		
		String hardwareVersion = (body.readByte()&0xff)+"."+(body.readByte()&0xff);
		byte _gpsState = body.readByte();
		String gpsState = ByteUtil.byteToBit(_gpsState);
		
		int gsmState = body.readByte();
		float nvolt = (float)(0.1 * body.readByte());
		float wvolt = (float)(0.1 * body.readShort());
		
		byte _switch1 = body.readByte();
		String switch1 = ByteUtil.byteToBit(_switch1);
		byte _switch2 = body.readByte();
		String switch2 = ByteUtil.byteToBit(_switch2);
		byte _switch3 = body.readByte();
		String switch3 = ByteUtil.byteToBit(_switch3);
		
		byte _gpsworkState = body.readByte();
		String gpsworkState = ByteUtil.byteToBit(_gpsworkState);
		
		short lac =  body.readShort(); //基站lac
		short rssi =   body.readShort(); //基站rssi
		
		int deviceid = msg.getHeader().getDeviceid();
		
		if(msg.getHeader().getSerial()%2==0){  // 取消 数据插入
			return null;
		}
		
		DBUtil.exec("INSERT INTO deviceinfo (did, sversion, hversion, gpsstate, gsmstate, nvolt, wvolt, switch1, switch2, switch3, gpsworkstate, lac, rssi) " +
				"VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)", deviceid, softVersion, hardwareVersion,gpsState, gsmState,nvolt,wvolt,switch1,
														switch2,switch3,gpsworkState, lac,rssi);
		
		DBUtil.exec("update deviceone set sversion=?, hversion=?, gpsstate=?, gsmstate=?, nvolt=?, wvolt=?, switch1=?, switch2=?, switch3=?,"
				+ " gpsworkstate=?, lac=?, rssi=?, ctime =now() where did =?", softVersion, hardwareVersion,gpsState, gsmState,nvolt,wvolt,switch1, switch2,
					switch3,gpsworkState, lac,rssi,  deviceid);
	
		return null;
	}
	
	//mLock(deviceid ,_switch1); // 解析机械钥匙 状态
	void mLock(int deviceid, byte state){
		String ss = ByteUtil.byteToBit(state);
		int s = Integer.parseInt(""+ss.charAt(1));  // 0-关闭, 1-打开
		DBUtil.exec("update deviceauth set mlock=? where id =?", s, deviceid);
	}
	
	/**
	 * MCU透传
	 * @param body
	 * @return
	 */
	public byte[] MCU(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		DBUtil.exec("insert into mtu(deviceid, data) values(?,?)", deviceid, ByteUtil.bytetoHexStr(body.array()));
		return null;
	}
	
	/**
	 * bluetoothData透传
	 * @param body
	 * @return
	 */
	public byte[] bluetoothData(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		
		return null;
	}
	
	/**
	 * 电瓶信息
	 * @param msg
	 * @return
	 */
	public byte[] voltInfo(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		parseVoltInfo(deviceid ,body);
		return null;
	}
	public byte[] batchvoltInfo(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		int cnt =  body.readByte();
		while(body.remaining()>0){
			byte []b = new byte[21]; 
			body.readBytes(b);
			parseVoltInfo(deviceid, IoBuffer.wrap(b));
		}
		return null;
	}
	
	public void parseVoltInfo(int deviceid, IoBuffer info){
		info.buf().order(ByteOrder.LITTLE_ENDIAN);
		info.readInt();
		
		int year = 2000 + info.readByte();
		int month = info.readByte();
		int day = info.readByte();
		int hour = info.readByte();
		int minute = info.readByte();
		int second = info.readByte();
		
		float volt = (float) (info.readShort()*0.1); //电压
		byte stat1 = info.readByte();
		String state1 = ByteUtil.byteToBit(stat1);
		float elec = (float) ((info.readByte()&0xff)*0.1); //电流
		byte stat2 = info.readByte();
		String state2 = ByteUtil.byteToBit(stat2);
		short pl = info.readShort();  // 当次运行最多频率
		int mlcnt = info.readInt();  // 当次脉冲数
		
		Calendar c = Calendar.getInstance();
		
		DBUtil.exec("INSERT INTO voltinfo(did, volt, elec, state1, state2, pl, mlcnt, ctime)" +
				" VALUES(?,?,?,?,?,?,?,?)", deviceid, volt, elec, state1, state2, pl, mlcnt, new Timestamp(c.getTimeInMillis()));
		DBUtil.exec("update  voltone set volt=?, elec=?, state1=?, state2=?, pl=?, mlcnt=?, ctime=? where did=?", 
				volt, elec, state1, state2, pl, mlcnt, new Timestamp(c.getTimeInMillis()), deviceid);
		
		final VoltInfo voltInfo = new VoltInfo(deviceid, volt, state1, elec, state2, pl, mlcnt, c);
		MessageThreadPool.executeMessageTask(new Runnable() {
			@Override
			public void run() {
				try{
					workout(voltInfo);
				}catch(Exception e){
					logger.info(e.getMessage(),e);
				}
			}
		});
	}
	
	/**
	 * 根据 上报的 电池信息计算
	 * @throws Exception
	 * msgid=c1, length=22, deviceid=2098 
	 */
	public void workout(VoltInfo voltInfo) throws Exception{
		String state1 = voltInfo.state1;
		String charge_s = state1.substring(3, 5);
		
		String _sql = "select life,energy_type,btype, t_u,t_i,cnt, curr_an,enery_milleage, rchange_percent,last_percent,av_u,curr_percent, "
				+ "c.ah,c.volt,a.state,max_pl,max_speed,energy_100, begint::date,charge_state,t,curr_milleage,"
				+ "(date_part('hour', endt- begint) + date_part('minute', endt- begint)/60) as hour, a.ctime from "
				+ "battery a left join deviceset c on c.deviceid = a.did where a.did = ?";
		Map<String, Object> map = DBUtil.getMap(_sql, voltInfo.deviceid);
		if(map.isEmpty()) return;
		Battery battery = null;
		StringBuffer sql = new StringBuffer("update battery set did=?");
		DBQuery query = new DBQuery(sql);
		query.setParams(voltInfo.deviceid);
		String jmsg = null;
		Date ctime = (Date) map.get("ctime");
		Calendar c =  Calendar.getInstance();
		c.setTime(ctime);
		int charge_state = -1;
		double chargetime =0;
		String state2 = voltInfo.state2;
		String run = state2.substring(0, 1);
		if("1".equals(run) || "00".equals(charge_s)){ // 无充电 不管无充电
			if("1".equals(run)){  //计算 里程
				 //报运行中 并且无充电, 此时为停车电压
				battery = Battery.parseBattery(voltInfo, map);
				battery.getLastPercent();
				query.add(", last_percent=?").setParams(battery.last_percent); 
				query.add(", cd_hour=?").setParams(battery.cd_hour);
				query.add(", last_mileage=?").setParams(battery.last_mileage);
				charge_state = 0;
				// 更新停车电压 tc_u charge_state last_percent  total_milleage curr_milleage energy_100
				battery.getMileage();
				query.add(", av_u=?").setParams(battery.av_u);
				query.add(", tc_u=?").setParams(voltInfo.volt);
				float  curr_percent = (float) map.get("curr_percent"); //上次充电后的电量, 充满为1
				if(curr_percent==1&& battery.last_percent<0.3){ // 上次充满电, 并且剩余电流 <0.3
					if((int)map.get("energy_type") == 1){  // 判断是否手动更新 百公里能耗
						double energy_100 = ((float)map.get("energy_100")+battery.energy_100)/2;
						query.add(", energy_100=?").setParams(energy_100);  // 百公里能耗平均
						query.add(", curr_percent=?").setParams(0); 
					}
				}
				//累计充满电到 30%电的里程
				query.add(", enery_milleage=enery_milleage+?").setParams(battery.current_mileage);
				if(voltInfo.c.get(Calendar.DATE) == c.get(Calendar.DATE)){ // 如果同一天
					query.add(", curr_milleage=curr_milleage+?").setParams(battery.current_mileage); 
				} else{
					query.add(", curr_milleage=?").setParams(battery.current_mileage); 
					//记录历史行驶里程
					historyMileages(c, map, 0, voltInfo.deviceid);
				}
				query.add(", total_milleage=total_milleage+?").setParams(battery.current_mileage); 
				if(voltInfo.pl>(int) map.get("max_pl")){
					query.add(", max_pl=?").setParams(voltInfo.pl);
				}
				if(battery.last_percent<0.2){  //剩余电量<0.2
					if((int)map.get("state")!=1){ //推送后修改为1
						query.add(", state=1");
						jmsg = "电池电量低于20%，请及时充电，过放电使用会影响电池寿命";
					}
					// 电池电量低于20%, 推送到 手机api端
					JPushUtil.pushVoltLow(voltInfo.deviceid, battery.last_percent);
				}
			}
			
		}else if("01".equals(charge_s)){ //充电中
			//判定是否第一次充电
			charge_state = 1;
			battery = Battery.parseBattery(voltInfo, map);
			battery.charge();
			int first = (int)map.get("charge_state");
			if(first==0 ||first == -1){ //更新 rchange_percent begint t_u t_i
				query.add(", rchange_percent=last_percent");
				query.add(", begint=?").setParams(voltInfo.c.getTime());
				//voltInfo.c.add(Calendar.MINUTE, 30);//不知道什么原因加了时间
				query.add(", endt=?").setParams(voltInfo.c.getTime());
				query.add(", t_u=?").setParams(voltInfo.volt);
				query.add(", t_i=?").setParams(voltInfo.elec);
				query.add(", cnt=1");
			}else{
				// 其他连续充电 累计操作 
				//cnt t_u t_i  last_percent curr_percent  endt
				// 使用 last_percent计算出curr_percent , 更新last_percent为curr_percent
				query.add(", cnt=cnt+1");
				query.add(", t_u=t_u+?").setParams(voltInfo.volt);
				query.add(", t_i=t_i+?").setParams(voltInfo.elec);
				query.add(", endt=?").setParams(voltInfo.c.getTime());
				query.add(", last_mileage=?").setParams(battery.last_mileage); 
				//battery.curr_percent 这个为 last_percent + 充电时间内充上的电量
				query.add(", last_percent=?").setParams(battery.curr_percent); 
				query.add(", cd_hour=?").setParams(battery.cd_hour);
			}
			
		}else if("11".equals(charge_s)  ){ //充电中充满电  || "10".equals(charge_s) 不充电充满电
			//计算更新 c_i c_u life last_percent  curr_an
			charge_state = 2; ////充满电
			battery = Battery.parseBattery(voltInfo, map);
			battery.getLastPercent();
			battery.add_percent=1; //充满电,使当前curr_percent >=1
			if(voltInfo.elec>0) battery.charge();
			float  rchange_percent = (float) map.get("rchange_percent");
			query.add(", endt=?").setParams(voltInfo.c.getTime());
			query.add(", last_percent=?").setParams(1);
			query.add(", last_mileage=?").setParams(battery.last_mileage); 
			query.add(", curr_percent=?").setParams(1);
			query.add(", enery_milleage=?").setParams(0);  //用来记录充满电到30% 点行走的路程
			if(rchange_percent!=0&& rchange_percent<0.3){ //是否上次百分比在50%以下,
				if(voltInfo.elec>0){
					query.add(", curr_an=?").setParams(battery.current_ah);
					query.add(", life=?").setParams(battery.life);
				}
				
				if((int)map.get("state")<2 && battery.life<0.8){ //充满电后修改为空
					query.add(", state=2");
					int life= (int)(battery.life*100);   // 
					jmsg ="您的电池储电量为"+life+"%，若无法满足您里程需求请至特约服务商";
				}
				// TODO 判断是否需要矫正 电压 容量
				if((int)map.get("state") == 0){
					// TODO 矫正后不再继续矫正 
					//String params = null;
					//DBUtil.exec("update deviceset set an =?, volt =? ,state=state+1", params);
				}
			}
			//
			if((int)map.get("state")<3){ //充满电后修改为空
				if(!query.getSql().contains("state")){
					query.add(", state=3");
					chargetime = battery.hour;
					if(((BigDecimal) map.get("t_i")).intValue()==0){
						chargetime +=20/60; //非充电添加 20分钟充电时间
					}
					jmsg ="电池已充满, 充电时长"+String.format("%.1f",chargetime)+"小时";
					JPushUtil.parseLife(voltInfo.deviceid, 0, 0, 0, 0, 1);
				}
			}
		}
		
		/**** 更新里程*****/
		if(voltInfo.c.get(Calendar.DATE) != c.get(Calendar.DATE)){ // 如果不是同一天
			if(!query.getSql().contains("curr_milleage")){  //如果上面已经有更新, 不重复更新
				query.add(", curr_milleage=?").setParams(0); 
				//记录历史行驶里程
				historyMileages(c, map, 0, voltInfo.deviceid);
			}
		}
		
		if("00".equals(charge_s)){
			if(!query.getSql().contains("state")){
				query.add(", state=0");
			}
		}
		
		//ctime
		query.add(", charge_state=?").setParams(charge_state);
		query.add(", ctime=now()");
		query.add(" where did =?").setParams(voltInfo.deviceid); 
		DBUtil.exec(query);
		
		if(jmsg != null){
			int uid =  getUid(voltInfo.deviceid);
//			if(uid == 0) JPushUtil.serverToClientPush(jmsg, voltInfo.deviceid); // 取消推送到 租车api
//			JPushUtil.checkPush(jmsg, uid);
			DBUtil.exec("insert into pushinfo(uid, title, content) values(?,?,?)", uid, "电池信息", jmsg);
		}else{
			JPushUtil.pushBattery(voltInfo.state1, voltInfo.state2, voltInfo.deviceid, chargetime);
		}
	}
	
	private void historyMileages(Calendar c, Map<String, Object> map, double curr_mileage, int did) {
		int date = c.get(Calendar.DAY_OF_YEAR);
		int i = date%7 + 1;  // 取余数+1, 存历史记录7天
		String sql = "update milleages set m"+i+" =? where did =?";
		Object curr_milleage = map.get("curr_milleage");
		int mi = (int) curr_mileage;
		if(curr_milleage!=null){
			mi+= Double.parseDouble(curr_milleage.toString());
		}
		DBUtil.exec(sql, mi, did );
	}

	/**
	 * 报警信息
	 * @param msg
	 * @return
	 * @throws Exception 
	 */
	public byte[] warnInfo(Message msg) throws Exception {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		parseWarnInfo(deviceid, body);
		return null;
	}
	
	public void parseWarnInfo(int deviceid, IoBuffer body){
		body.readInt();
		
		int year = 2000 + body.readByte();
		int month = body.readByte();
		int day = body.readByte();
		int hour = body.readByte();
		int minute = body.readByte();
		int second = body.readByte();
		
		byte s = body.readByte(); // 报警状态
		String state = ByteUtil.byteToBit(s);
		Calendar c = Calendar.getInstance();
		
		DBUtil.exec("insert into warninfo(did, state, ctime) values(?,?,?)", deviceid, state, new Timestamp(c.getTimeInMillis()));
		JPushUtil.pushWarn(state, deviceid);
		
	}
	
	/**
	 * 批量上报报警信息
	 * @param msg
	 * @return
	 */
	public byte[] batchwarnInfo(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int cnt =  body.readByte();
		while(body.remaining()>0){
			byte [] info = new byte[11];
			body.readBytes(info);
			parseWarnInfo(msg.getHeader().getDeviceid(),  IoBuffer.wrap(info));
		}
		return null;
	}
	
	TimedCache<String, Object> fileMap = new TimedCache<>(30*60*1000);
	public byte[] uppackage(Message msg) { // 上传数据包
		IoBuffer body = msg.getBodyBuf();
		byte [] version = new byte[4];
		body.readBytes(version);
		short packTotal = body.readShort();
		short packIndex = body.readShort();
		String v = getsoftversion(version);
		byte[] _file = (byte[])fileMap.get(v);
		if(_file == null){
			fileMap.clear();
			Map<String, Object> map = DBUtil.getMap("select * from appconfig where key =?", "deviceversion");
			String filepath = (String) map.get("value2")+"/"+v.substring(0,5) +"/"+v;  // uploadpath +/version 文件夹+/ 文件 
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			try {
				FileUtil.copy(new FileInputStream(filepath), out);
				_file = out.toByteArray();
				fileMap.put(v, _file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		ByteBuf file = Unpooled.copiedBuffer(_file);
		byte[] p = null;
		logger.info("packIndex-->"+packIndex+" packTotal-->"+packTotal);
		int sbytesize = 512; // 单包的传输大小
		
		if(packTotal == packIndex){
			p = file.copy((packIndex-1)*sbytesize, file.readableBytes()-(packIndex-1)*sbytesize).array();
		}else{
			p = file.copy((packIndex-1)*sbytesize, sbytesize).array();
		}
		
		/* 发送 分包过去*/
		IoBuffer resBody = getLittleBuf();
		resBody.writeBytes(version); //升级版本号
		resBody.writeShort(packTotal);
		resBody.writeShort(packIndex);
		resBody.writeShort((short)p.length); 
		resBody.writeBytes(p);
		resBody.flip();
		return resBody.readBytes(0, resBody.limit());
	}
	
	public byte[] checkupdate(final Message msg) { //收到确认命令 后下发升级
		IoBuffer body = msg.getBodyBuf();
		byte[] version = new byte[4];
		body.readBytes(version);
		final String v = getsoftversion(version);
		int state = body.readByte();
		if(state ==1){
			//发送升级命令
			MessageThreadPool.executeMessageTask(new Runnable() {
				@Override
				public void run() {
					try {Thread.sleep(300);} catch (InterruptedException e) {
					}
					/*发送升级命令*/
					HttpUtil.getStr("http://127.0.0.1:7070/sendcmd?cmds="+25
							+"&deviceid="+msg.getHeader().getDeviceid()+"&code="+01+","+v, "UTF-8");
				}
			});
		}
		IoBuffer resBody = getLittleBuf();
		resBody.writeBytes(version);
		resBody.writeByte(state);  //回复校验状态
		resBody.flip();
		return resBody.readBytes(0, resBody.limit());
	}
	
	/**
	 * 客户端检查版本号
	 * @param msg
	 * @return
	 */
	public byte[] checkversion(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int state =  body.readByte();
		if(state != 1) return null;
		byte[] v = new byte[4];
		body.readBytes(v);
		String minversion = getsoftversion(v);
		IoBuffer resBody = getLittleBuf();
		int sbytesize = 512;  // 每包的大小
		resBody.writeByte(3);
		Map<String, Object> map = DBUtil.getMap("select * from appconfig where key =? limit 1", "deviceversion");
		
		String filepath = (String) map.get("value2");
		
		String vpath = filepath + "/" + minversion.substring(0, 5); //  文件路径 upload/version/文件 
		File f = new File(vpath);
		File ff[] = f.listFiles();
		File max = getMax(ff);
		
		byte version [] = new byte[4];
		byte version_1 [] = new byte[4];
		String[] value1=  max.getName().split("\\.");
		 version = new byte[]{(byte)Integer.parseInt(value1[0]),(byte)Integer.parseInt(value1[1]) 
				,(byte)Integer.parseInt(value1[2]),(byte)Integer.parseInt(value1[3]) };
		 version_1  = new byte[]{(byte)Integer.parseInt(value1[0]),(byte)Integer.parseInt(value1[1]) 
				,(byte)Integer.parseInt(value1[2]),(byte)(Integer.parseInt(value1[3])-100) };
		
		resBody.writeBytes(version_1);
		resBody.writeByte(2); // 每包大小
		resBody.writeBytes(getFileSet(vpath+"/"+getsoftversion(version_1), sbytesize));
		
		resBody.writeBytes(version);
		resBody.writeByte(2);// 每包大小
		resBody.writeBytes(getFileSet(vpath+"/"+getsoftversion(version), sbytesize));
		resBody.flip();
		return resBody.readBytes(0, resBody.limit());

	}
	
	public byte[] getFileSet(String filepath, int sbytesize){
		IoBuffer buf = getLittleBuf(6);
		FileInputStream ff = null;
		try {
			ff = new FileInputStream(filepath);
			long totalSize = ff.available();
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			FileUtil.copy(ff, out);
			short total = (short) Math.ceil((double)totalSize/sbytesize) ;// 文件长度
			buf.writeShort(total);
			int crc_32 = (int)ByteUtil.crc32(out.toByteArray()); 
			buf.writeInt(crc_32);
			return buf.array();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 上传simcard
	 * @param msg
	 * @return
	 */
	public byte[] simcaid(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int length = body.readByte();  //长度
		byte[] regmsg = new byte[length];
		body.readBytes(regmsg);
		
		//保存simcard
		String simcaid = new  String(regmsg);
		DBUtil.exec("update deviceauth set simcaid=? where id=?", simcaid, msg.getHeader().getDeviceid());
		return null;
	}
	
	/**
	 * 控制器错误信息上报
	 * @param msg
	 * @return
	 */
	public byte[] errmsg(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		DBUtil.exec("insert into mtu(deviceid, data, type) values(?,?,1)", deviceid, ByteUtil.bytetoHexStr(body.array()));
		return null;
	}
	
	/**
	 * 套套机状态上报
	 * @param msg
	 * @return
	 */
	public byte[] ttstate(Message msg) {
		IoBuffer body = msg.getBodyBuf();
		int deviceid = msg.getHeader().getDeviceid();
		
		DBUtil.exec("insert into mtu(deviceid, data, type) values(?,?,1)", deviceid, ByteUtil.bytetoHexStr(body.array()));
		
		return null;
	}
	
	
	public static File getMax(File[] files) {
		File f = null;
		for (int i = 0; i < files.length; i++) {
			File _f = files[i];
			if (i == 0)	f = _f;
			if (f.getName().compareTo(_f.getName()) < 0) {
				f = _f;
			}
		}
		return f;
	}
	

}
